package com.fishery.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fishery.entity.GlobalException;
import com.fishery.entity.Result;
import com.fishery.entity.StatusCode;
import com.fishery.order.entity.ConstantValue;
import com.fishery.order.entity.client.*;
import com.fishery.order.entity.vo.SaleOrderVo;
import com.fishery.order.entity.vo.SearchOrderConditionVo;
import com.fishery.order.service.client.BaseClient;
import com.fishery.order.service.client.FactoryClient;
import com.fishery.order.service.client.LogisticsClient;
import com.fishery.order.entity.Customer;
import com.fishery.order.entity.Order;
import com.fishery.order.mapper.CustomerMapper;
import com.fishery.order.mapper.OrderMapper;
import com.fishery.order.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fishery.order.service.client.RefrigeratoryClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author run 、 ghost
 * @since 2021-01-31
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

	@Autowired
	private OrderMapper orderMapper;

	@Autowired
	private CustomerMapper customerMapper;

	@Autowired
	private BaseClient baseClient;

	@Autowired
	private LogisticsClient logisticsClient;

	@Autowired
	private FactoryClient factoryClient;

	@Autowired
	private RefrigeratoryClient refrigeratoryClient;


	@Override
	public boolean createOrder(Order order) {
		//非法输入检查
		if (StringUtils.isEmpty(order.getBaseId())) {
			throw new GlobalException(StatusCode.ERROR, "发货的基地id不能为空");
		}
		if (StringUtils.isEmpty(order.getTargetId())) {
			throw new GlobalException(StatusCode.ERROR, "收货人id不能为空");
		}
		if (StringUtils.isEmpty(order.getProductId())) {
			throw new GlobalException(StatusCode.ERROR, "产品编号不能为空");
		}
		if (order.getAmount() == null || order.getAmount() < 0) {
			throw new GlobalException(StatusCode.ERROR, "产品数量不合法");
		}
		if (order.getMoney() == null || order.getMoney().doubleValue() < 0) {
			throw new GlobalException(StatusCode.ERROR, "订单金额不合法");
		}
		if (order.getWeight() == null || order.getWeight() < 0) {
			throw new GlobalException(StatusCode.ERROR, "产品数量不合法");
		}
		if (order.getSourceType() == null || order.getSourceType() <= 0 || order.getSourceType() > 3) {
			throw new GlobalException(StatusCode.ERROR, "发货方类型不合法");
		}
		// 如果收货方是从客户列表中选取的话
		if (order.getTargetType().equals(1) || order.getTargetType().equals(2)) {
			Customer customer = customerMapper.selectById(order.getTargetId());
			if (customer != null) {
				order.setReceiveAddress(customer.getReceiveAddress());
				order.setAddressLatitude(customer.getAddressLatitude());
				order.setAddressLongitude(customer.getAddressLongitude());
				order.setTargetName(customer.getCustomerName());
				order.setTargetType(customer.getCustomerType());
				order.setPhoneNumber(customer.getPhoneNumber());
			}
		}
		if (order.getTargetType() == null || order.getTargetType() <= 0 || order.getTargetType() > 4) {
			throw new GlobalException(StatusCode.ERROR, "客户类型不合法");
		}
		if (StringUtils.isEmpty(order.getReceiveAddress())) {
			throw new GlobalException(StatusCode.ERROR, "收货地址不能为空");
		}

		boolean ret = false;
		// 调用库存接口
		if (order.getSourceType().equals(1)) {
			// 调用养殖基地库存接口
			ret = baseClient.decreaseAmountAndWeightOfRecord(
					ProductInventoryVo.valueOf(order.getProductId(), order.getAmount(), order.getWeight()))
					.isFlag();
		} else if (order.getSourceType().equals(2)) {
			// 调用加工厂库存接口
			ret = factoryClient.setProductCount(order.getProductId(), -order.getWeight()).isFlag();
		} else if (order.getSourceType().equals(3)) {
			// 调用冷库库存接口
			Object data = refrigeratoryClient.saveRefrigeratoryOutInfo(order).getData();
			if (data != null) {
				String productId = JSON.toJSONString(data);
				order.setProductId(productId.substring(1, productId.length() - 1));
				ret = true;
			}
		}
		ret = ret ? orderMapper.insert(order) > 0 : ret;
		return ret;
	}


	@Override
	public boolean deleteOrder(String orderId) {
		Order order = orderMapper.selectById(orderId);
		if (order == null) {
			throw new GlobalException(StatusCode.ERROR, "订单不存在，无法删除");
		}
		boolean ret = false;
		if (order.getLogisticsId() == null) {
			// 调用库存接口，将重量和数量进行归还到库存
			if (order.getSourceType().equals(1)) {
				// 调用养殖基地库存接口
				ret = baseClient.increaseAmountAndWeightOfRecord(
						ProductInventoryVo.valueOf(order.getProductId(), order.getAmount(), order.getWeight()))
						.isFlag();
			} else if (order.getSourceType().equals(2)) {
				// 调用加工厂库存接口
				ret = factoryClient.setProductCount(order.getProductId(), order.getWeight()).isFlag();
			} else {
				// 调用冷库库存接口
				ret = refrigeratoryClient.deleteRefrigeratoryOutInfoById(order.getProductId()).isFlag();
			}
		}
		ret = ret ? orderMapper.deleteById(orderId) > 0 : ret;
		return ret;
	}

	@Override
	public Order searchOrderById(String orderId) {
		return orderMapper.selectById(orderId);
	}

	@Override
	public boolean deliverOrder(String orderId) {
		Order order = orderMapper.selectById(orderId);
		if (order == null) {
			throw new GlobalException(StatusCode.ERROR, "该订单不存在");
		}
		if (order.getLogisticsId() != null) {
			throw new GlobalException(StatusCode.ERROR, "该订单已发货");
		}

		Result result = baseClient.getBaseById(order.getBaseId());
		if (result.getStatusCode() != StatusCode.OK.getCode()) {
			throw new GlobalException(StatusCode.ERROR, "订单所属基地信息获取失败");
		}

		Base base = JSON.parseObject(JSON.toJSONString(result.getData()), Base.class);
		if (base == null) {
			throw new GlobalException(StatusCode.ERROR, "订单基地不存在");
		}

		//创建物流订单
		OrderVo logisticOrder = new OrderVo();
		StationVo startStation = new StationVo();
		StationVo arrivalStation = new StationVo();
		//设置物流订单信息
		logisticOrder.setBaseId(order.getBaseId());
		logisticOrder.setProductId(order.getProductId());
		logisticOrder.setLogisticsStartStation(startStation);
		logisticOrder.setLogisticsArrivalStation(arrivalStation);
		logisticOrder.setLogisticsOrderCreateBy(base.getCreator());
		//设置物流出发站信息
		startStation.setBaseId(order.getBaseId());
		startStation.setLogisticsStationAddress(base.getAddress());
		startStation.setLogisticsStationLatitude(base.getPositionLatitude());
		startStation.setLogisticsStationLongitude(base.getPositionLongitude());
		startStation.setLogisticsStationType(order.getSourceType() < 2
				? order.getSourceType() - 1
				: order.getSourceType() + 1);

		//设置物流终点站信息
		arrivalStation.setBaseId(order.getBaseId());
		arrivalStation.setLogisticsStationAddress(order.getReceiveAddress());
		arrivalStation.setLogisticsStationLongitude(order.getAddressLongitude());
		arrivalStation.setLogisticsStationLatitude(order.getAddressLatitude());
		arrivalStation.setPhoneNumber(order.getPhoneNumber());
		arrivalStation.setLogisticsStationType(order.getTargetType());

		//调用物流的接口创建物流订单
		Result logisticsResult = logisticsClient.createLogisticOrder(logisticOrder);
		if (logisticsResult.getStatusCode() != StatusCode.OK.getCode()) {
			throw new GlobalException(StatusCode.ERROR, "物流订单创建失败");
		}

		//将物流信息加进订单中
		String logisticsId = (String) logisticsResult.getData();
		order.setLogisticsId(logisticsId);
		return orderMapper.updateById(order) > 0;
	}

	@Override
	public List<Order> searchOrderOfBase(String baseId) {
		QueryWrapper<Order> wrapper = new QueryWrapper<>();
		wrapper.eq("base_id", baseId)
				.or()
				.eq("target_id", baseId);
		return orderMapper.selectList(wrapper);
	}

	@Override
	public IPage<Order> searchOrderOfBase(String baseId, Integer page, Integer size) {
		if (page <= 0) {
			page = 1;
		}
		if (size <= 0) {
			size = 5;
		}
		Page<Order> orderPage = new Page<>(page, size);
		QueryWrapper<Order> wrapper = new QueryWrapper<>();
		wrapper.eq("base_id", baseId)
				.or()
				.eq("target_id", baseId);
		return orderMapper.selectPage(orderPage, wrapper);
	}

	@Override
	public boolean receiveOrder(String logisticsId) {
		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("logistics_id", logisticsId);
		Order order = orderMapper.selectOne(queryWrapper);
		if (order == null || order.getStatus().equals(1)) {
			throw new GlobalException(StatusCode.ERROR, "该订单已经送达，无需进行操作");
		}
		// 进行将数据刷到加工厂、冷库基地
		if (order.getTargetType().equals(ConstantValue.TARGET_FACTORY_TYPE)) {
			// 加工厂基地
			CompletableFuture.runAsync(() -> {
				Base base = JSON.parseObject(JSON
						.toJSONString(baseClient.getBaseById(order.getBaseId()).getData()), Base.class);
				MaterialInventory materialInventory = new MaterialInventory();
				materialInventory.setBaseId(order.getTargetId());
				materialInventory.setMaterialId(order.getProductId());
				materialInventory.setMaterialName(order.getProductName());
				materialInventory.setMaterialWeight(order.getWeight());
				materialInventory.setSupplierType(order.getSourceType());
				materialInventory.setSupplierBase(base.getName());
				materialInventory.setSupplierName(base.getCreator());
				factoryClient.createMaterial(materialInventory);
			});
		} else if (order.getTargetType().equals(ConstantValue.TARGET_REFRIGERATORY_TYPE)) {
			// 冷库基地
			CompletableFuture.runAsync(() -> {
				Base base = JSON.parseObject(JSON
						.toJSONString(baseClient.getBaseById(order.getBaseId()).getData()), Base.class);
				RefrigeratoryPrepareEnter refrigeratoryPrepareEnter = new RefrigeratoryPrepareEnter();
				refrigeratoryPrepareEnter.setProductId(order.getProductId());
				refrigeratoryPrepareEnter.setProductName(order.getProductName());
				refrigeratoryPrepareEnter.setProductWeight(order.getWeight());
				refrigeratoryPrepareEnter.setBelongBaseId(order.getTargetId());
				refrigeratoryPrepareEnter.setSupplierType(String.valueOf(order.getSourceType()));
				refrigeratoryPrepareEnter.setSuppliersSource(base.getName());
				refrigeratoryPrepareEnter.setSupplierName(base.getCreator());
				refrigeratoryClient.saveRefrigeratoryEnter(refrigeratoryPrepareEnter);
			});
		}
		order.setStatus(1);
		return orderMapper.updateById(order) > 0;
	}

	@Override
	public boolean updateOrder(com.fishery.order.entity.vo.OrderVo orderVo) {
		Order oldOrder = orderMapper.selectById(orderVo.getId());
		if (!StringUtils.isEmpty(orderVo.getProductId())
				&& !oldOrder.getProductId().equals(orderVo.getProductId())) {
			throw new GlobalException(StatusCode.ERROR, "产品编号无法修改");
		}
		if (!StringUtils.isEmpty(oldOrder.getLogisticsId())) {
			throw new GlobalException(StatusCode.ERROR, "订单已发货，无法修改");
		}

		boolean ret = true;
		if (orderVo.getAmount() != null && !orderVo.getAmount().equals(oldOrder.getAmount())
				|| orderVo.getWeight() != null && !orderVo.getWeight().equals(oldOrder.getWeight())) {
			// 计算delt（相差值 = 原来的数据 - 更新后的数据）,后面调用增加接口即可
			int deltAmount = oldOrder.getAmount() - orderVo.getAmount();
			double deltWeight = oldOrder.getWeight() - orderVo.getWeight();
			// 调用库存接口，处理数量和重量问题
			if (oldOrder.getSourceType().equals(1)) {
				// 调用养殖基地库存接口
				ret = baseClient.increaseAmountAndWeightOfRecord(
						ProductInventoryVo.valueOf(oldOrder.getProductId(), deltAmount, deltWeight))
						.isFlag();
			} else if (oldOrder.getSourceType().equals(2)) {
				// 调用加工厂库存接口
				ret = factoryClient.setProductCount(orderVo.getProductId(),
						oldOrder.getWeight() - orderVo.getWeight()).isFlag();
			} else {
				// 调用冷库库存接口
				ret = refrigeratoryClient.updateOrder(orderVo).isFlag();
			}
		}
		try {
			ret = ret ? orderMapper.updateOrderById(orderVo) > 0 : ret;
			return ret;
		} catch (
				Exception e) {
			return false;
		}
	}


	@Override
	public SaleOrderVo searchSaleOrderOfBase(SearchOrderConditionVo conditionVo) {
		return orderMapper.selectSaleOrderByCondition(conditionVo.getBaseId(), conditionVo.getBegin(), conditionVo.getEnd());
	}

	@Override
	public Result traceInformationByProductIdAndSourceType(String productId, String sourceType) {
		if (ConstantValue.SOURCE_FARMING_TYPE.equals(sourceType)) {
			// 溯源养殖基地
			return baseClient.traceInformationOfProduct(productId, 5, 1);
		} else if (ConstantValue.SOURCE_FACTORY_TYPE.equals(sourceType)) {
			// 溯源加工厂基地
			return factoryClient.getMessageOfBatch(productId);
		} else if (ConstantValue.SOURCE_REFRIGERATORY_TYPE.equals(sourceType)) {
			// 溯源冷库基地
			return refrigeratoryClient.getProduct(productId);
		}
		return null;
	}

	@Override
	public Map<String, Object> getSourceTypeAndProductIdById(String traceId) {
		Order order = orderMapper.selectById(traceId);
		if (order == null
				|| StringUtils.isEmpty(order.getSourceType())
				|| StringUtils.isEmpty(order.getBaseId())) {
			return null;
		}
		Map<String, Object> resultMap = new ConcurrentHashMap<>(4);
		getSourceTypeAndProductIdAndType(resultMap, order.getProductId(), String.valueOf(order.getSourceType()));
		return resultMap;
	}

	private void getSourceTypeAndProductIdAndType(Map<String, Object> resultMap, String productId, String type) {
		Object o = resultMap.get(type);
		if (o == null) {
			List<String> list = new ArrayList<>(2);
			list.add(productId);
			resultMap.put(type, list);
		} else {
			((List) o).add(productId);
		}
		if (ConstantValue.SOURCE_FARMING_TYPE.equals(type)) {
			// 来源是养殖基地，终止递归
			return;
		} else if (ConstantValue.SOURCE_FACTORY_TYPE.equals(type)) {
			// 来源是加工厂，进行递归
			Map<String, Object> data = (Map<String, Object>) factoryClient.getSourceMessage(productId).getData();
			if (data != null) {
				getSourceTypeAndProductIdAndType(resultMap,
						(String) data.get("productId"), String.valueOf(data.get("sourceType")));
			}
		} else if (ConstantValue.SOURCE_REFRIGERATORY_TYPE.equals(String.valueOf(type))) {
			// 来源是冷库，进行递归
			Map<String, Object> data = (Map<String, Object>) refrigeratoryClient.selectProductInfo(productId).getData();
			if (data != null) {
				getSourceTypeAndProductIdAndType(resultMap, (String) data.get("productId"),
						(String) data.get("supplierType"));
			}
		}
	}

}
